/******************************************************/
/*
/* Manejo de un Display de Cristal Liquido LCD 16X4   */
/* de 16 caracteres por 4 lineas, con una interface   */
/* de 4 lineas:                                       */
/*
/*	LCD		            PIC
/* ------------------------------------
/*	D4  (11)		-->	RB0
/*	D5  (12)		-->	RB1
/*	D6  (13)		-->	RB2
/*	D7  (14)		-->	RB3
/*
/*	RS  (4)			-->	RC0
/*	RW  (5)			-->	RC1
/*	E   (6)			-->	RC2
/*
/******************************************************/
/* Conexiones del LCD al Microcontrolador */
#define	PIN_RS		LATEbits.LATE0	// Define la Columna 1
#define	PIN_RW	LATEbits.LATE1	// Define la Columna 2
#define	PIN_E		LATEbits.LATE2	// Define la Columna 3

/* Configuracion del Display y cursor */
#define DON				0b00001111  /* Display encendido   */
#define DOFF				b00001011  /* Display apagado     */
#define CURSOR_HOME		0b00000010  /* Cursor posicion inicial    */
#define CURSOR_ON		0b00001111  /* Cursor encendido    */
#define CURSOR_OFF		0b00001101  /* Cursor apagado      */
#define BLINK_ON			0b00001111  /* Cursor con parpadeo */
#define BLINK_OFF			0b00001110  /* Cursor sin parpadeo */
#define CLEAR				0b00000001  /* Display encendido   */

/* Modo de entrada */
#define INCREMENT			0b00000110  /* Incrementa la posicion del cursor */
#define DECREMENT		0b00000100  /* Decrementa la posicion del cursor */


/* Configuracion de los desplazamientos del cursor y del Display*/
#define SHIFT_CUR_LEFT		0b00010011  /* Corrimiento del cursor a la izquierda  */
#define SHIFT_CUR_RIGHT		0b00010111  /* Corrimiento del cursor a la derecha    */
#define SHIFT_DISP_LEFT		0b00011011  /* Corrimiento del display a la izquierda */
#define SHIFT_DISP_RIGHT		0b00011111  /* Corrimiento del display a la derecha   */


/* Funciones de inicializacion */
#define NIBLE				0b00000010  /* interface a 4 bits */
#define FOUR_BIT			0b00101111  /* Interface a 4-bit  */
#define EIGHT_BIT			0b00111111  /* Interface a 8-bit  */
#define LINE_5X7			0b00110011  /* Una linea, caracter 5x7 */
#define LINE_5X10			0b00110111  /* Una linea, caracter 5x10 */
#define LINES_5X7			0b00111011  /* Dos lineas. character 5x7 */


/* Lineas de trabajo */
#define DDRAM_LINEA_1		0b10000000	/* Linea 1 */
#define DDRAM_LINEA_2		0b11000000	/* Linea 2 */
#define DDRAM_LINEA_3		0b10010000	/* Linea 3 */
#define DDRAM_LINEA_4		0b11010000	/* Linea 4 */


/* Configuracion del puerto */
#define Config_Puerto		0b00000000	/* RC<0:6> como salidas */
#define Mascara				0b00001111	/* Parte baja del Byte  */


/* Prototipos de funciones */
void Inicializa_LCD(void);			/* Inicializa LCD */
void Comando_LCD(char);			/* Indica al LCD un comando */
void Dato_LCD(char);				/* Indica al LCD un caracter */
void Datos_LCD(const rom char *buffer);	/* escribe una cadena desde la memoria de programa al LCD */
void Dato_String_LCD(char *buffer);		/* escribe una cadena desde la memoria de datos al LCD */

//**********************************************************
/* Inicializacion del LCD segun fabricante */
//**********************************************************
void Inicializa_LCD(void)
{
	int i;
	Delay10TCYx(110);			/* Retardo mayor a 100 useg. */
	LATC = NIBLE;				/* Interface de 4 bits RC<0:3> */
	PIN_RS = 0;
	PIN_RW = 0;
	PIN_E = 1;

	Delay1KTCYx(5);				/* Retardo de 5 mseg. */	
	PIN_E = 0;
	Delay1KTCYx(15);				/* Retardo de 15 mseg. */

	/* Funcion set,  DL = 0, N = 1, F = 0 */
	/* Dos lineas, caracter de 5X7 e interface a 4 bits */	
	Comando_LCD(LINES_5X7 & FOUR_BIT);

	/* Display ON, D = 1, C = 1, B = 1 */
	/* Display encendido, cursor encendido con parpadeo */
	Comando_LCD(DON & CURSOR_ON & BLINK_ON);

	/* limpia el display */
	Comando_LCD(CLEAR);

	/* Entry Mode Set */
	/* Incremento del cursor */
	Comando_LCD(INCREMENT);
}

//**********************************************************
/* Indica al LCD comandos */ 
//**********************************************************
void Comando_LCD(char dato)
{
	char temp;						/* variable auxiliar */

	Delay1KTCYx(10);				/* Retardo de 10 mseg. */
	temp = dato;						/* Respaldo del dato original */
	dato = dato >> 4;					/* Corrimiento del nible alto */
	LATC = dato;
	PIN_RS = 0;
	PIN_RW = 0;
	PIN_E = 1;
	Delay1KTCYx(5);				/* Retardo de 5 mseg. */	
	PIN_E = 0;
	LATC = temp;
	PIN_RS = 0;
	PIN_RW = 0;
	PIN_E = 1;
	Delay1KTCYx(5);				/* Retardo de 5 mseg. */	
	PIN_E = 0;
}

//**********************************************************
/* Manda datos al LCD */
//**********************************************************
void Dato_LCD(char dato)
{
	char temp;						/* variable auxiliar */

	Delay1KTCYx(10);				/* Retardo de 10 mseg. */
	temp = dato;						/* Respaldo del dato original */
	dato = dato >> 4;					/* Corrimiento del nible alto */
	LATC = dato;
	PIN_RS = 1;
	PIN_RW = 0;
	PIN_E = 1;
	Delay1KTCYx(5);				/* Retardo de 5 mseg. */	
	PIN_E = 0;
	LATC = temp;
	PIN_RS = 1;
	PIN_RW = 0;
	PIN_E = 1;
	Delay1KTCYx(5);				/* Retardo de 5 mseg. */	
	PIN_E = 0;
}
//**********************************************************
//	Escribe una cadena desde memoria de programa al LCD
//**********************************************************
void Datos_LCD(const rom char *buffer)
{
	while(*buffer)                  // Write data to LCD up to null
    {
		Delay1KTCYx(5);					/* Retardo de 5 mseg. */	
        Dato_LCD(*buffer); // Write character to LCD
        buffer++;               // Increment buffer
	}
    return;
}
//**********************************************************
//	Escribe una cadena desde memoria de datos al LCD
//**********************************************************
void Dato_String_LCD(char *buffer)
{
	while(*buffer)                  // Write data to LCD up to null
    {
		Delay1KTCYx(5);					/* Retardo de 5 mseg. */	
        Dato_LCD(*buffer); // Write character to LCD
        buffer++;               // Increment buffer
	}
    return;
}
